home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995 June: Reference Library / Dev.CD Jun 95 / Dev.CD Jun 95.toast / What's New? / New System Software Extensions / QuickDraw 3D ß / Programming / SampleCode / Modeller ƒ / Modeller_document.c < prev    next >
Encoding:
Text File  |  1995-04-15  |  24.7 KB  |  861 lines  |  [TEXT/MPS ]

  1. //    modeller_document.c
  2. //
  3. //    Document handling routines.
  4. //        
  5. //    Author:        Rob Johnston
  6. //    Date:        Monday, February 10, 1992
  7. //
  8. //    Copyright © 1992-94 Apple Computer, Inc., All Rights Reserved
  9. //
  10. //    Modification History:
  11. //
  12. //    11/26/94    nick    clean up, remove old TE references from dragtext, remove
  13. //                        all other dead code.
  14. //                        Modify CloseDocument & CloseAllDocuments to return a Boolean.
  15. //    01/26/95    nick    parameterized NewDocument to take a (possibly null) group
  16. //                        and viewhints.  Factored this routine as it was way too long
  17. //
  18. // to do: store the document reference as a handle in the window's refcon
  19. //
  20.  
  21. #include <Drag.h>
  22. #include <QuickDraw.h>
  23.  
  24.  
  25. #include "Modeller_globals.h"
  26. #include "Modeller_prototypes.h"
  27. #include "Modeller_resources.h"
  28.  
  29. #include "QD3DDrawContext.h"
  30. #include "QD3DCamera.h"
  31. #include "QD3DView.h"
  32. #include "QD3DLight.h"
  33. #include "QD3DGeometry.h"
  34. #include "QD3DSet.h"
  35. #include "QD3DTransform.h"
  36. #include "QD3DShader.h"
  37. #include "QD3DShader.h"
  38. #include "QD3DMath.h"
  39. #include "QD3DIO.h"
  40.  
  41. #include "Modeller_camera.h"
  42. #include "Modeller_document.h"
  43. #include "Modeller_file.h"
  44.  
  45. extern pascal OSErr MyTrackingHandler(short message, WindowPtr theWindow,
  46.                                          void *handlerRefCon, DragReference theDrag);
  47.  
  48. extern pascal OSErr MyReceiveDropHandler(WindowPtr theWindow, void *handlerRefCon,
  49.                                          DragReference theDrag);
  50.  
  51. //----------------------------------------------------------------------
  52. TQ3Status ModellerDocument_NewLights( DocumentPtr theDocument ) 
  53. {
  54.     TQ3GroupObject            lightGroup;
  55.     TQ3LightObject            light;
  56.     TQ3PointLightData        pointData;
  57.     TQ3LightData                ambientData;
  58.     
  59.     lightGroup = Q3LightGroup_New();
  60.  
  61.     pointData.lightData.isOn        = kQ3True;
  62.     pointData.lightData.brightness    = 0.950;
  63.     pointData.lightData.color.r     = 1.0;
  64.     pointData.lightData.color.g     = 1.0;
  65.     pointData.lightData.color.b     = 1.0;
  66.     pointData.location.x            = -10.0;
  67.     pointData.location.y            = 10.0;
  68.     pointData.location.z            = 30.0;
  69.     pointData.castsShadows            = kQ3False;
  70.     pointData.attenuation            = kQ3AttenuationTypeNone;
  71.     
  72.     light = Q3PointLight_New(&pointData);
  73.     Q3Group_AddObject(lightGroup, light);
  74.     Q3Object_Dispose(light);
  75.  
  76.     ambientData.isOn        = kQ3True;
  77.     ambientData.brightness    = 0.70;
  78.     ambientData.color.r     = 0.4;
  79.     ambientData.color.g     = 0.4;
  80.     ambientData.color.b     = 0.4;
  81.     
  82.     light = Q3AmbientLight_New(&ambientData);
  83.     Q3Group_AddObject(lightGroup, light);
  84.     Q3Object_Dispose(light);
  85.  
  86.     pointData.lightData.isOn        = kQ3False;
  87.     pointData.lightData.brightness    = 0.80;
  88.     pointData.lightData.color.r     = 1.0;
  89.     pointData.lightData.color.g     = 0.0;
  90.     pointData.lightData.color.b     = 0.0;
  91.     pointData.location.x            = -10.0;
  92.     pointData.location.y            = 0.0;
  93.     pointData.location.z            = 5.0;
  94.     pointData.castsShadows            = kQ3False;
  95.     pointData.attenuation            = kQ3AttenuationTypeInverseDistance;
  96.     
  97.     light = Q3PointLight_New(&pointData);
  98.     Q3Group_AddObject(lightGroup, light);
  99.     Q3Object_Dispose(light);
  100.  
  101.     pointData.lightData.isOn        = kQ3False;
  102.     pointData.lightData.brightness    = 0.80;
  103.     pointData.lightData.color.r     = 0.0;
  104.     pointData.lightData.color.g     = 1.0;
  105.     pointData.lightData.color.b     = 0.0;
  106.     pointData.location.x            = 10.0;
  107.     pointData.location.y            = 0.0;
  108.     pointData.location.z            = 5.0;
  109.     pointData.castsShadows            = kQ3False;
  110.     pointData.attenuation            = kQ3AttenuationTypeInverseDistance;
  111.     
  112.     light = Q3PointLight_New(&pointData);
  113.     Q3Group_AddObject(lightGroup, light);
  114.     Q3Object_Dispose(light);
  115.  
  116.  
  117.     pointData.lightData.isOn        = kQ3False;
  118.     pointData.lightData.brightness    = 0.80;
  119.     pointData.lightData.color.r     = 0.0;
  120.     pointData.lightData.color.g     = 0.0;
  121.     pointData.lightData.color.b     = 1.0;
  122.     pointData.location.x            = 10.0;
  123.     pointData.location.y            = 0.0;
  124.     pointData.location.z            = 5.0;
  125.     pointData.castsShadows            = kQ3False;
  126.     pointData.attenuation            = kQ3AttenuationTypeInverseDistance;
  127.     
  128.     light = Q3PointLight_New(&pointData);
  129.     Q3Group_AddObject(lightGroup, light);
  130.     Q3Object_Dispose(light);
  131.  
  132.     Q3View_SetLightGroup(theDocument->theView, lightGroup);
  133.     Q3Object_Dispose(lightGroup);
  134. //        
  135.     {
  136. #if defined(ESCHER_VER_15) && ESCHER_VER_15
  137.  
  138.         TQ3ColorRGB                        ellipsoidColor;
  139.         TQ3EllipsoidData                    ellipsoidData;
  140.         TQ3GeometryObject                ellipsoid;
  141.  
  142.  
  143.         TQ3RotateTransformData            rotateData;
  144.         
  145.         theDocument->dynamicLights = Q3DisplayGroup_New();
  146.         
  147.         ellipsoidData.origin.x = -10.0;
  148.         ellipsoidData.origin.y = 0.0;
  149.         ellipsoidData.origin.z = 5.0;
  150.         
  151.         ellipsoidData.orientation.x = 0.0;
  152.         ellipsoidData.orientation.y = 1.0;
  153.         ellipsoidData.orientation.z = 0.0;
  154.         
  155.         ellipsoidData.majorRadius.x = 0.0;
  156.         ellipsoidData.majorRadius.y = 0.0;
  157.         ellipsoidData.majorRadius.z = 1.0;
  158.         
  159.         ellipsoidData.minorRadius.x = 1.0;
  160.         ellipsoidData.minorRadius.y = 0.0;
  161.         ellipsoidData.minorRadius.z = 0.0;
  162.  
  163.         ellipsoidData.ellipsoidAttributeSet = Q3AttributeSet_New();
  164.         
  165.         /* Red light ball */
  166.         ellipsoidColor.r = 1.0;
  167.         ellipsoidColor.g = 0.0;
  168.         ellipsoidColor.b = 0.0;
  169.         
  170.         Q3AttributeSet_Add( ellipsoidData.ellipsoidAttributeSet, 
  171.         kQ3AttributeTypeDiffuseColor, &ellipsoidColor);
  172.  
  173.         Q3AttributeSet_Add(ellipsoidData.ellipsoidAttributeSet, 
  174.         kQ3AttributeTypeSpecularColor, &ellipsoidColor);
  175.     
  176.         ellipsoid = Q3Ellipsoid_New(&ellipsoidData);
  177.         Q3Object_Dispose(ellipsoidData.ellipsoidAttributeSet);
  178.         theDocument->light1 = Q3OrderedDisplayGroup_New();
  179.         Q3Group_AddObject(theDocument->light1, ellipsoid);
  180.         Q3Object_Dispose(ellipsoid);
  181.  
  182.         rotateData.axis = kQ3AxisY;
  183.         rotateData.radians = 0.0;
  184.         
  185.         theDocument->lightXform1 = Q3RotateTransform_New(&rotateData);
  186.         Q3Group_AddObject(theDocument->light1, theDocument->lightXform1);
  187.         
  188.         Q3Group_AddObject(theDocument->dynamicLights, theDocument->light1);
  189.         
  190.         /* Green light ball */
  191.         ellipsoidData.origin.x = 10.0;
  192.         ellipsoidData.origin.y = 0.0;
  193.         ellipsoidData.origin.z = 5.0;
  194.  
  195.         ellipsoidData.ellipsoidAttributeSet = Q3AttributeSet_New();
  196.         
  197.         ellipsoidColor.r = 0.0;
  198.         ellipsoidColor.g = 1.0;
  199.         ellipsoidColor.b = 0.0;
  200.         Q3AttributeSet_Add( ellipsoidData.ellipsoidAttributeSet, 
  201.         kQ3AttributeTypeDiffuseColor, (const void *) &ellipsoidColor);
  202.  
  203.         Q3AttributeSet_Add(ellipsoidData.ellipsoidAttributeSet, 
  204.         kQ3AttributeTypeSpecularColor, &ellipsoidColor);
  205.     
  206.         ellipsoid = Q3Ellipsoid_New(&ellipsoidData);
  207.         Q3Object_Dispose(ellipsoidData.ellipsoidAttributeSet);
  208.         theDocument->light2 = Q3OrderedDisplayGroup_New();
  209.         Q3Group_AddObject(theDocument->light2, ellipsoid);
  210.         Q3Object_Dispose(ellipsoid);                            
  211.  
  212.         theDocument->lightXform2 = Q3RotateTransform_New(&rotateData);
  213.         Q3Group_AddObject(theDocument->light2, theDocument->lightXform2);
  214.  
  215.         Q3Group_AddObject(theDocument->dynamicLights, theDocument->light2);
  216.         
  217.         /* Blue light ball */
  218.         ellipsoidData.origin.x = 5.0;
  219.         ellipsoidData.origin.y = 0.0;
  220.         ellipsoidData.origin.z = 10.0;
  221.  
  222.         ellipsoidData.ellipsoidAttributeSet = Q3AttributeSet_New();
  223.         
  224.         ellipsoidColor.r = 0.0;
  225.         ellipsoidColor.g = 0.0;
  226.         ellipsoidColor.b = 1.0;
  227.         Q3AttributeSet_Add( ellipsoidData.ellipsoidAttributeSet, 
  228.         kQ3AttributeTypeDiffuseColor, (const void *) &ellipsoidColor);
  229.  
  230.         Q3AttributeSet_Add(ellipsoidData.ellipsoidAttributeSet, 
  231.         kQ3AttributeTypeSpecularColor, &ellipsoidColor);
  232.     
  233.         ellipsoid = Q3Ellipsoid_New(&ellipsoidData);
  234.         Q3Object_Dispose(ellipsoidData.ellipsoidAttributeSet);
  235.         theDocument->light3 = Q3OrderedDisplayGroup_New();
  236.         Q3Group_AddObject(theDocument->light3, ellipsoid);
  237.         Q3Object_Dispose(ellipsoid);                            
  238.  
  239.         rotateData.axis = kQ3AxisX;
  240.         theDocument->lightXform3 = Q3RotateTransform_New(&rotateData);
  241.         Q3Group_AddObject(theDocument->light3, theDocument->lightXform3);
  242.  
  243.         Q3Group_AddObject(theDocument->dynamicLights, theDocument->light3);
  244. #endif        
  245.     }
  246.     
  247.     theDocument->animateLights = kQ3False;
  248.  
  249.     return(kQ3Success);
  250. }
  251.  
  252. //-----------------------------------------------------------------------------------
  253. TQ3CameraObject ModellerDocument_NewCamera(WindowPtr theWindow)
  254. {
  255.     TQ3ViewAngleAspectCameraData    perspectiveData;
  256.     TQ3CameraObject                camera;
  257.     
  258.     TQ3Point3D                     from     = { 0.0, 0.0, 30.0 };
  259.     TQ3Point3D                     to         = { 0.0, 0.0, 0.0 };
  260.     TQ3Vector3D                     up         = { 0.0, 1.0, 0.0 };
  261.  
  262.     float                         fieldOfView = .52359333333;
  263.     float                         hither         =  0.001;
  264.     float                         yon         =  1000;
  265.     
  266.     TQ3Status                    returnVal = kQ3Failure ;
  267.  
  268.  
  269.     perspectiveData.cameraData.placement.cameraLocation     = from;
  270.     perspectiveData.cameraData.placement.pointOfInterest     = to;
  271.     perspectiveData.cameraData.placement.upVector             = up;
  272.  
  273.     perspectiveData.cameraData.range.hither    = hither;
  274.     perspectiveData.cameraData.range.yon     = yon;
  275.  
  276.     perspectiveData.cameraData.viewPort.origin.x = -1.0;
  277.     perspectiveData.cameraData.viewPort.origin.y = 1.0;
  278.     perspectiveData.cameraData.viewPort.width = 2.0;
  279.     perspectiveData.cameraData.viewPort.height = 2.0;
  280.     
  281.     perspectiveData.fov                = fieldOfView;
  282.     perspectiveData.aspectRatioXToY    =
  283.         (float) (theWindow->portRect.right - theWindow->portRect.left) / 
  284.         (float) (theWindow->portRect.bottom - theWindow->portRect.top);
  285.         
  286.     camera = Q3ViewAngleAspectCamera_New(&perspectiveData);
  287.  
  288.     return camera ;
  289. }
  290.  
  291. //--------------------------------------------------------------------------------
  292.  
  293. #ifdef PODIUM_APP
  294.  
  295. TQ3DrawContextObject ModellerDocument_NewPixmapDrawContext( DocumentPtr theDocument )
  296. {
  297.     TQ3PixmapDrawContextData    myDrawContextData;
  298.     TQ3ColorARGB                clearColor = {1.0, 1.0, 1.0, 1.0 };
  299.     TQ3DrawContextObject        myDrawContext ;
  300.     GWorldPtr                     theGWorld ;
  301.     PixMapHandle                hPixMap ;
  302.     Rect                        srcRect ;
  303.     
  304.     theGWorld = theDocument->geometriesOffscreen ;
  305.     
  306.     //    Fill in draw context data.
  307.     myDrawContextData.drawContextData.clearImageMethod = kQ3ClearMethodWithColor;
  308.     myDrawContextData.drawContextData.clearImageColor  = clearColor;
  309.  
  310.     myDrawContextData.drawContextData.paneState = kQ3False;
  311.     myDrawContextData.drawContextData.maskState = kQ3False;
  312.     
  313.     myDrawContextData.drawContextData.doubleBufferState = kQ3False;
  314.     
  315.     hPixMap = GetGWorldPixMap(theGWorld);
  316.     LockPixels(hPixMap);
  317.  
  318.     srcRect = theGWorld->portRect;
  319.  
  320.     myDrawContextData.pixmap.width = srcRect.right  - srcRect.left;
  321.     myDrawContextData.pixmap.height= srcRect.bottom - srcRect.top;
  322.     
  323.     myDrawContextData.pixmap.rowBytes = (**hPixMap).rowBytes & 0x7FFF;
  324.     myDrawContextData.pixmap.pixelType = kQ3PixelTypeRGB32;
  325.     myDrawContextData.pixmap.pixelSize = 32;
  326.  
  327.     myDrawContextData.pixmap.bitOrder  = kQ3EndianBig;
  328.     myDrawContextData.pixmap.byteOrder = kQ3EndianBig;
  329.     
  330.     myDrawContextData.pixmap.image        = (**hPixMap).baseAddr;
  331.     
  332.     return Q3PixmapDrawContext_New(&myDrawContextData);
  333. }
  334.  
  335. #endif
  336.  
  337. //--------------------------------------------------------------------------------
  338.  
  339. TQ3DrawContextObject ModellerDocument_NewDrawContext( WindowPtr theWindow )
  340. {
  341.     TQ3DrawContextData        myDrawContextData;
  342.     TQ3MacDrawContextData    myMacDrawContextData;
  343.     TQ3DrawContextObject        myDrawContext ;
  344.     TQ3ColorARGB                clearColor = {1.0, 0.8, 0.8, 0.8};    // lt gray
  345.  
  346.     //    Fill in draw context data.
  347.     myDrawContextData.clearImageMethod = kQ3ClearMethodWithColor;
  348.     myDrawContextData.clearImageColor = clearColor;
  349.     myDrawContextData.pane.min.x = (theWindow->portRect).left;
  350.     myDrawContextData.pane.max.x = (theWindow->portRect).right; 
  351.     myDrawContextData.pane.min.y = (theWindow->portRect).top;
  352.     myDrawContextData.pane.max.y = (theWindow->portRect).bottom;
  353.     myDrawContextData.paneState = kQ3False;
  354.     myDrawContextData.maskState = kQ3False;
  355.     myDrawContextData.doubleBufferState = kQ3True;
  356.  
  357.     myMacDrawContextData.drawContextData = myDrawContextData;
  358.     
  359.     myMacDrawContextData.library = kQ3Mac2DLibraryNone;
  360.     myMacDrawContextData.window = (CWindowPtr) theWindow;
  361.     myMacDrawContextData.grafPort = nil;
  362.     myMacDrawContextData.viewPort = nil;
  363.     
  364.     //    Create draw context and return it, if it’s nil the caller must handle
  365.     myDrawContext = Q3MacDrawContext_New(&myMacDrawContextData) ;
  366.  
  367.     return myDrawContext ;
  368. }
  369.  
  370.  
  371. //--------------------------------------------------------------------------------
  372. TQ3Status    ModellerDocument_UpdateView( DocumentPtr theDocument, TQ3SharedObject viewHints )
  373. {
  374.     TQ3Object                tempObject;
  375.     TQ3CameraObject            camera ;
  376.     
  377.     if( theDocument->theView == NULL)
  378.         return kQ3Failure ;
  379.         
  380.     ModellerDocument_NewLights( theDocument ) ;
  381.  
  382.     if( viewHints == NULL ) {
  383.         
  384.         // if we were called with null viewhints, then just set up
  385.         // sensible defaults for the current document
  386.  
  387.         camera = ModellerDocument_NewCamera( theDocument->theWindow ) ;
  388.         if( camera != NULL ) {
  389.             Q3View_SetCamera(theDocument->theView, camera );
  390.             Q3Object_Dispose(camera);
  391.         }
  392.         else 
  393.             return kQ3Failure ;
  394.         
  395.         Q3View_SetRendererByType(theDocument->theView, kQ3RendererTypeWireFrame);
  396.     }
  397.     else {
  398.     
  399.         // we think we have valid viewhints, so attempt to 
  400.         // get the information we need from the viewhints 
  401.         // passed in, where we dont have an item, then make
  402.         // a sensible default.
  403.         
  404.         // renderer information
  405.         Q3ViewHints_GetRenderer(viewHints, &tempObject);
  406.         if (tempObject != NULL)
  407.         {
  408.             Q3View_SetRenderer(theDocument->theView, tempObject);
  409.             Q3Object_Dispose(tempObject);
  410.         }
  411.         else
  412.             Q3View_SetRendererByType(theDocument->theView, kQ3RendererTypeWireFrame);
  413.     
  414.         // camera information
  415.         Q3ViewHints_GetCamera(viewHints, &tempObject);
  416.         if (tempObject != NULL) {
  417.             Q3View_SetCamera(theDocument->theView, tempObject);
  418.             Q3Object_Dispose(tempObject);
  419.         }    
  420.         else {
  421.             camera = ModellerDocument_NewCamera( theDocument->theWindow ) ;
  422.             if( camera != NULL ) {
  423.                 Q3View_SetCamera(theDocument->theView, camera );
  424.                 Q3Object_Dispose(camera);
  425.             }
  426.             else 
  427.                 return kQ3Failure ;
  428. #ifndef PODIUM_APP                    
  429.             AdjustCamera(theDocument,
  430.                                 theDocument->theWindow->portRect.right - theDocument->theWindow->portRect.left,
  431.                                 theDocument->theWindow->portRect.bottom - theDocument->theWindow->portRect.top);    
  432.  
  433. #else
  434.             AdjustCamera(theDocument,
  435.                                 theDocument->geometriesOffscreen->portRect.right - theDocument->geometriesOffscreen->portRect.left,
  436.                                 theDocument->geometriesOffscreen->portRect.bottom - theDocument->geometriesOffscreen->portRect.top);    
  437. #endif
  438.         }        
  439.         
  440.         // light information
  441.         Q3ViewHints_GetLightGroup(viewHints, &tempObject);
  442.         if (tempObject != NULL) {
  443.             Q3View_SetLightGroup(theDocument->theView, tempObject);
  444.             Q3Object_Dispose(tempObject);
  445.         }            
  446.         else {
  447.             ModellerDocument_NewLights( theDocument ) ;
  448.         }
  449.     
  450.     }
  451.     
  452.     // replace the existing view hints
  453.     if( theDocument->viewHints ) {
  454.         Q3Object_Dispose(theDocument->viewHints);
  455.     }
  456.     theDocument->viewHints = Q3ViewHints_New(theDocument->theView);
  457.     
  458.     SetPort( (GrafPtr)theDocument->theWindow) ;
  459.     InvalRect( &theDocument->theWindow->portRect ) ;
  460.     
  461.     return kQ3Success ;
  462. }
  463.  
  464. //--------------------------------------------------------------------------------
  465. //    NewDocument is called when a new document window is needed. Creation of
  466. //    document data structures is handled here.
  467. //
  468.  
  469. DocumentPtr NewDocument( TQ3SharedObject viewHints, TQ3GroupObject group )
  470. {
  471.     DocumentPtr theDocument;
  472.     WindowPtr        theWindow;
  473.     Rect            theRect = { 0, 0, 16, 16 };
  474.     Point            thePoint;
  475.     TQ3Param2D        uvValues = {-1.0, -1.0};
  476.     
  477.     TQ3DrawContextObject        theDrawContext ;
  478.     TQ3CameraObject            camera ;
  479.     TQ3AttributeSet            viewSet;
  480.     
  481.     if (gDocumentCount == MaxDocumentCount)
  482.         return( (DocumentPtr )nil );
  483.         
  484.         
  485.     // make sure the pointer is initialised to nil, because we rely on
  486.     // the fields being non nil in order to dispose of the correctly.
  487.     theDocument = gDocumentList[gDocumentCount++] =
  488.                             (DocumentPtr )NewPtrClear(sizeof(DocumentRecord));
  489.  
  490. #ifdef PODIUM_APP
  491.     {
  492.         // for podium set up two GWorlds, on for the bg picture, one for the 
  493.         // pixmap draw context that we'll draw the geomentries into
  494.         
  495.         Rect        defaultGeometryRect = { 0, 0, 200, 200 } ;
  496.         GWorldPtr    savedGWorld ;
  497.         GDHandle    savedGDH ;
  498.         
  499.         GetGWorld( &savedGWorld, &savedGDH ) ;
  500.         
  501.         if( NewGWorld(&theDocument->bgOffscreen, 16, &defaultGeometryRect, nil, nil, 0L ) != noErr ) {
  502.             CloseDocument( theDocument ) ;
  503.             return NULL ;
  504.         }
  505.         SetGWorld( theDocument->bgOffscreen, nil ) ;
  506.         EraseRect( &theDocument->bgOffscreen->portRect ) ;
  507.         
  508.         if( NewGWorld(&theDocument->screenBuffer, 16, &defaultGeometryRect, nil, nil, 0L ) != noErr ) {
  509.             CloseDocument( theDocument ) ;
  510.             return NULL ;
  511.         }
  512.         SetGWorld( theDocument->screenBuffer, nil ) ;
  513.         EraseRect( &theDocument->screenBuffer->portRect ) ;
  514.         
  515.         if( NewGWorld(&theDocument->geometriesOffscreen, 32, &defaultGeometryRect, nil, nil, 0L ) != noErr ) {
  516.             CloseDocument( theDocument ) ;
  517.             return NULL ;
  518.         }
  519.         SetGWorld( theDocument->geometriesOffscreen, nil ) ;
  520.         EraseRect( &theDocument->geometriesOffscreen->portRect ) ;
  521.         theDocument->dropArea = defaultGeometryRect ;
  522.         
  523.         // create a 1-bit GW for the mask
  524.         if( NewGWorld( &theDocument->maskOffscreen, 1, &theDocument->geometriesOffscreen->portRect, nil, nil, 0L)  != noErr ) {
  525.             CloseDocument( theDocument ) ;
  526.             return NULL ;
  527.         }
  528.         SetGWorld( theDocument->maskOffscreen, nil ) ;
  529.         EraseRect( &theDocument->maskOffscreen->portRect ) ;
  530.         
  531.         SetGWorld( savedGWorld, savedGDH ) ;
  532.         
  533.         theDocument->currentInterpolation = kQ3InterpolationStyleVertex;
  534.     }
  535. #endif
  536.  
  537.  
  538.     theWindow = GetNewCWindow(WindowTemplateID, 0L, (WindowPtr) -1L);
  539.  
  540.     if (theWindow == nil)
  541.         return( (DocumentPtr )nil );
  542.     
  543.     theDocument->theWindow = theWindow ;
  544.                     
  545.     SetWRefCon(theWindow, (long)theDocument ) ;
  546.  
  547.     SetPort(theWindow);
  548.  
  549. #ifndef PODIUM_APP
  550.     // only want to set the bg color up for podium
  551.     {
  552.         RGBColor color = { 0xFFFF, 0xFFFF, 0xFFFF};
  553.         
  554.         color.red *= 0.8;
  555.         color.green *= 0.8;
  556.         color.blue *= 0.8;
  557.         
  558.         RGBBackColor(&color);
  559.         EraseRect(&theWindow->portRect);
  560.         
  561.         color.blue = color.green = color.red  =  0xFFFF;
  562.         RGBBackColor(&color);
  563.     }
  564. #endif
  565.  
  566.     thePoint = *((Point *) (&theWindow->portRect.top));
  567.     LocalToGlobal(&thePoint);
  568.     if (thePoint.h < 10) {
  569.         MoveWindow(theWindow, InitialH, InitialV, false);
  570.     }
  571.  
  572.     theDocument->fRefNum = 0;
  573.  
  574.     // zero out the file spec
  575.     theDocument->theFileSpec.vRefNum = 0 ;
  576.     theDocument->theFileSpec.parID = 0 ;
  577.     theDocument->theFileSpec.name[0] = '\0' ;
  578.     
  579.     theDocument->dirty = false;
  580.     
  581.     // set up the draw context, camera and lights
  582. #ifndef PODIUM_APP
  583.     theDrawContext = ModellerDocument_NewDrawContext( theWindow ) ;
  584. #else
  585.     theDrawContext = ModellerDocument_NewPixmapDrawContext( theDocument ) ;
  586.  
  587. #endif
  588.     if( theDrawContext != NULL ) {
  589.         TQ3ColorRGB            clearColor = {1.0, 1.0, 1.0};
  590.  
  591.         theDocument->theView = Q3View_New();
  592.     
  593.         Q3View_GetDefaultAttributeSet(theDocument->theView, &viewSet);
  594.         Q3AttributeSet_Add(viewSet, 
  595.             kQ3AttributeTypeSpecularColor, &clearColor);
  596.         Q3AttributeSet_Add(viewSet, 
  597.             kQ3AttributeTypeSurfaceUV, &clearColor);
  598.         Q3AttributeSet_Add(viewSet, 
  599.             kQ3AttributeTypeShadingUV, &clearColor);
  600.         Q3Object_Dispose(viewSet);
  601.         
  602.         Q3View_SetDrawContext(theDocument->theView, theDrawContext);
  603.         Q3Object_Dispose(theDrawContext);
  604.     }
  605.     else
  606.         return NULL ;
  607.  
  608.                             
  609.     InstallTrackingHandler(NewDragTrackingHandlerProc(MyTrackingHandler), theWindow, (void *) theDocument);
  610.     InstallReceiveHandler(NewDragReceiveHandlerProc(MyReceiveDropHandler), theWindow, (void *) theDocument);
  611.  
  612.     Q3Matrix4x4_SetIdentity(&theDocument->modelRotation);
  613.     
  614.     theDocument->animateModel = kQ3False;
  615.     theDocument->light = kQ3False;
  616.     theDocument->shaded = kQ3False;
  617.     theDocument->documentGroup = nil;
  618.     
  619. #ifndef PODIUM_APP
  620.     theDocument->currentInterpolation = kQ3InterpolationStyleNone;
  621. #endif
  622.  
  623.     theDocument->backfacingStyle = Q3BackfacingStyle_New(kQ3BackfacingStyleRemove ) ;
  624.     theDocument->viewHints = Q3ViewHints_New(theDocument->theView);\
  625.     theDocument->illuminationShader = Q3PhongIllumination_New();
  626.  
  627.  
  628.     return(theDocument);
  629. }
  630.  
  631.  
  632. //----------------------------------------------------------------------------------
  633. //    CloseDocument is called when a document window is being closed. Storage
  634. //    of the document file and disposal of document data structures is handled
  635. //    here.
  636.  
  637. Boolean CloseDocument( DocumentPtr theDocument )
  638.  
  639. {    short            index, response;
  640.     Str255            theName, theVerb;
  641.     Boolean            couldCloseIt = false ;
  642.  
  643.     index = 0;
  644.     
  645.     while ((gDocumentList[index] != theDocument) && (index < MaxDocumentCount))
  646.         index++;
  647.  
  648.     if (gDocumentList[index] == theDocument) {
  649.  
  650.         if (theDocument->dirty) {
  651.             GetWTitle(theDocument->theWindow, theName);
  652.             GetIndString(theVerb, FileStringsID, (gQuitting) ? slQuittingIndex : slClosingIndex);
  653.             ParamText( (ConstStr255Param)&theName, (ConstStr255Param) &theVerb, (ConstStr255Param) "", (ConstStr255Param) "");
  654.             SetCursor(&qd.arrow);
  655.             
  656.             // check with the user - do they want to save this thing
  657.             response = Alert(idSaveChangesALRT, 0L);
  658.  
  659.             if (response == 1) {            // Save
  660.             
  661.                 // check to see that we were able to save the 
  662.                 // document as requested to by the user
  663.                 
  664.                 if (!DidSaveDocument(theDocument)) {
  665.                 
  666.                     // signal that we are not quitting (if we were actually trying)
  667.                     gQuitting = false;
  668.                     
  669.                     // signal that we couldn't save this document
  670.                     couldCloseIt = false ;
  671.                     
  672.                     return couldCloseIt;
  673.                 }
  674.                 
  675.             } else if (response == 3) {        /* Don't Save */
  676.                 ;
  677.             } else {                        /* Cancel */
  678.                 gQuitting = false ;
  679.                 
  680.                 // signal that we didn't actually want to close this document
  681.                 couldCloseIt = false ;
  682.                 
  683.                 return couldCloseIt;
  684.             }
  685.         }
  686.         
  687.         // if we are here we can assume the document has been saved (if required) and 
  688.         // that we can junk all of the data structures associated with the document
  689.  
  690.         // if it has a file associated, close it
  691.         if (theDocument->fRefNum) {
  692.             FSClose(theDocument->fRefNum);
  693.         }
  694.  
  695.         // remove our drag manager handlers
  696.         RemoveTrackingHandler(NewDragTrackingHandlerProc(MyTrackingHandler), theDocument->theWindow);
  697.         RemoveReceiveHandler(NewDragReceiveHandlerProc(MyReceiveDropHandler), theDocument->theWindow);
  698.  
  699.         // and we can dispose of the window
  700.         if(theDocument->theWindow)
  701.             DisposeWindow(theDocument->theWindow);
  702.  
  703.         // close any holes left in the array we 
  704.         // have for storing our document objects
  705.         while (index < MaxDocumentCount) {
  706.             gDocumentList[index] = gDocumentList[index + 1];
  707.             index++;
  708.         }
  709.  
  710.         // dispose of our QuickDraw 3d view object
  711.         if(theDocument->theView)
  712.             Q3Object_Dispose(theDocument->theView);
  713.  
  714.         if(theDocument->viewHints)
  715.             Q3Object_Dispose(theDocument->viewHints);
  716.  
  717.         // if we have a group associated with the document, then delete that
  718.         if(theDocument->documentGroup)
  719.             Q3Object_Dispose(theDocument->documentGroup);
  720.  
  721.         // dispose of the lights we set up for this document
  722.         if(theDocument->dynamicLights)
  723.             Q3Object_Dispose(theDocument->dynamicLights);
  724.  
  725.         if(theDocument->light1) {
  726.             Q3Object_Dispose(theDocument->light1);
  727.             Q3Object_Dispose(theDocument->lightXform1);
  728.         }
  729.         
  730.         if(theDocument->light2) {
  731.             Q3Object_Dispose(theDocument->light2);
  732.             Q3Object_Dispose(theDocument->lightXform2);
  733.         }
  734.         
  735.         if(theDocument->light3) {
  736.             Q3Object_Dispose(theDocument->light3);
  737.             Q3Object_Dispose(theDocument->lightXform3);
  738.         }
  739.  
  740.         if(theDocument->backfacingStyle) {
  741.             Q3Object_Dispose(theDocument->backfacingStyle);
  742.         }
  743.  
  744.         if(theDocument->illuminationShader) {
  745.             Q3Object_Dispose(theDocument->illuminationShader);
  746.         }
  747.  
  748. #ifdef PODIUM_APP
  749.  
  750.         if(theDocument->bgOffscreen != nil ) {
  751.             DisposeGWorld(theDocument->bgOffscreen) ;
  752.         }
  753.         
  754.         if(theDocument->screenBuffer != nil ) {
  755.             DisposeGWorld(theDocument->screenBuffer) ;
  756.         }
  757.         
  758.         if(theDocument->geometriesOffscreen != nil ) {
  759.             DisposeGWorld(theDocument->geometriesOffscreen) ;
  760.         }
  761.         
  762.         if(theDocument->maskOffscreen != nil ) {
  763.             DisposeGWorld(theDocument->maskOffscreen) ;
  764.         }
  765.         
  766. #endif
  767.  
  768.         // finally dispose of the storage used for the document and 
  769.         // decrement the document count
  770.         if( theDocument != nil )
  771.             DisposPtr((Ptr) theDocument);
  772.         gDocumentCount--;
  773.         
  774.         // signal that we closed this document
  775.         couldCloseIt = true ;
  776.         return couldCloseIt;
  777.         
  778.     }
  779.  
  780.     // signal that we could't actually close this document
  781.     couldCloseIt = false ;
  782.     return couldCloseIt;
  783. }
  784.  
  785.  
  786. //----------------------------------------------------------------------------------
  787. //    Closes all document windows.
  788. //
  789.  
  790. Boolean CloseAllDocuments( void )
  791. {
  792.     short    index ;
  793.     
  794.     for( index = gDocumentCount - 1; index >= 0; index-- ) {
  795.         if(CloseDocument(gDocumentList[ index ]) == false)
  796.             return false;
  797.     }
  798.     return true ;
  799. }
  800.  
  801.  
  802.  
  803. //----------------------------------------------------------------------------------
  804. //    DoActivateDocument is called when an event is received that reports that
  805. //    a document window is being either activated or deactivated.
  806.  
  807. void DoActivateDocument(DocumentPtr theDocument, short activate)
  808. {
  809.  
  810.     if (theDocument) {
  811.         if (activate) {
  812.         
  813.             // do whatever you'd like to do for a activate event
  814.             LoadScrap() ;
  815.  
  816.         } else {
  817.         
  818.             // do whatever you'd like to do for a deactivate event
  819.             UnloadScrap() ;
  820.         }
  821.     }
  822. }
  823.  
  824.  
  825. //----------------------------------------------------------------------------------
  826. //    If the given WindowPtr is a pointer to a document window, this function
  827. //    returns a pointer to a document data structure. If the window is not
  828. //    a document window, the function returns nil.
  829.  
  830. DocumentPtr GetDocumentFromWindow(WindowPtr theWindow)
  831. {
  832.     short        index = 0;
  833.     DocumentPtr theDocument;
  834.  
  835.     if( theWindow == nil )
  836.         return((DocumentPtr ) 0L);
  837.  
  838.     theDocument = (DocumentPtr ) (((WindowPeek) theWindow)->refCon);
  839.  
  840.     while ((gDocumentList[index] != theDocument) && (index < gDocumentCount))
  841.         index++;
  842.  
  843.     if (gDocumentList[index] == theDocument)
  844.         return(theDocument);
  845.     else
  846.         return((DocumentPtr ) 0L);
  847. }
  848.  
  849.  
  850.  
  851. TQ3Status InitializeGroup(TQ3GroupObject group)
  852. {
  853.     TQ3ShaderObject    illuminationShader = Q3PhongIllumination_New();
  854.  
  855.     Q3Group_AddObject(group, illuminationShader);
  856.     Q3Object_Dispose(illuminationShader);
  857.     return(kQ3Success);
  858. }
  859.  
  860.  
  861.